package com.hksj.common.quartz.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hksj.common.core.exception.ApplicationException;
import com.hksj.common.quartz.adapter.DeviceInfoAdapter;
import com.hksj.common.quartz.dto.CronJobDTO;
import com.hksj.common.quartz.entity.CronJob;
import com.hksj.common.quartz.entity.CronJobDevice;
import com.hksj.common.quartz.mapper.CronJobMapper;
import com.hksj.common.quartz.query.CronJobQuery;
import com.hksj.common.quartz.vo.CronJobDeviceVO;
import com.hksj.common.quartz.vo.CronJobVO;
import org.quartz.JobDataMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;

/**
 *  服务类
 * @author chenxingqing
 */
@Service("cronJobService")
public class CronJobService extends ServiceImpl<CronJobMapper, CronJob> {
    @Autowired
    private QuartzService quartzService;
    @Autowired
    private CronJobDeviceService cronJobDeviceService;
    @Autowired(required = false)
    private DeviceInfoAdapter deviceInfoAdapter;

    String pattern = "0 %s %s ? * %s";

    @Transactional
    public void saveCronJob(CronJobDTO dto) {
        Integer count = lambdaQuery()
                .eq(CronJob::getGroupName, dto.getGroupName())
                .eq(CronJob::getName, dto.getName())
                .ne(!ObjectUtils.isEmpty(dto.getId()), CronJob::getId, dto.getId())
                .count();
        if (count > 0) {
            throw new ApplicationException("定时任务名称重复");
        }
        CronJob cronJob = new CronJob();
        BeanUtils.copyProperties(dto,cronJob);
        saveOrUpdate(cronJob);

        cronJobDeviceService.lambdaUpdate()
                .eq(CronJobDevice::getJobId, cronJob.getId())
                .remove();

        if (!ObjectUtils.isEmpty(dto.getDeviceIdList())){
            List<CronJobDevice> deviceList = new ArrayList<>();
            CronJobDevice tCronJobDevice = null;
            for (String deviceId : dto.getDeviceIdList()) {
                tCronJobDevice = new CronJobDevice();
                tCronJobDevice.setJobId(cronJob.getId());
                tCronJobDevice.setDeviceId(deviceId);
                deviceList.add(tCronJobDevice);
            }
            cronJobDeviceService.saveBatch(deviceList);
        }
    }


    public void delCronJob(Long id) {
        CronJob cronJob = getById(id);
        if (cronJob.getStatus() == 1){
            throw new ApplicationException("运行中的任务无法删除，请先暂停任务");
        }

        quartzService.removeJob(cronJob.getName(), cronJob.getGroupName());
        removeById(id);
    }

    public void pauseJob(Long id) {
        CronJob cronJob = getById(id);
        quartzService.pauseJob(cronJob.getName(), cronJob.getGroupName());
        cronJob.setStatus(0);
        updateById(cronJob);
    }

    public void resumeJob(Long id) {
        CronJob cronJob = getById(id);
        quartzService.resumeJob(cronJob.getName(), cronJob.getGroupName());
        cronJob.setStatus(1);
        updateById(cronJob);
    }


    public void startJob(CronJob cronJob){
        try {
            Class clazz = Class.forName(cronJob.getJobClass());
            String cron = String.format(pattern, cronJob.getMinute(), cronJob.getHour(), cronJob.getWeek());
            JobDataMap dataMap = new JobDataMap();
            dataMap.put("jobId",cronJob.getId());
            quartzService.updateJob(cronJob.getName(),cronJob.getGroupName(),clazz,cron,dataMap);
        }catch (Exception e){
            throw new ApplicationException("启动任务失败");
        }
    }

    public void startJob(Long id) {
        CronJob cronJob = getById(id);
        startJob(cronJob);
        cronJob.setStatus(1);
        updateById(cronJob);
    }

    public IPage<CronJob> pageCronJob(CronJobQuery query) {
        Page<CronJob> page = new Page<>(query.getPageNum(), query.getPageSize());
        List<CronJob> list = baseMapper.pageCronJob(query,query.getDisAblePage() ? null : page);
        page.setRecords(list);
        return page;
    }

    public void initCronJob() {
        List<CronJob> list = lambdaQuery().eq(CronJob::getStatus, 1).list();
        for (CronJob cronJob : list) {
            startJob(cronJob);
        }
    }

    public CronJobVO getCronJob(Long id) {
        CronJobVO cronJobVO = new CronJobVO();
        CronJob cronJob = getById(id);
        BeanUtils.copyProperties(cronJob,cronJobVO);
        List<CronJobDeviceVO> deviceList = baseMapper.listDevice(id);
        if (!ObjectUtils.isEmpty(deviceInfoAdapter)){
            deviceInfoAdapter.wrapDeviceInfo(deviceList);
        }
        cronJobVO.setDeviceList(deviceList);
        return cronJobVO;
    }
}
